package com.becapps.easydownloader.service; import android.os.Handler; import android.os.Looper; import android.util.Log; public class FfmpegThread extends Thread { private static final String DEBUG_TAG = "FfmpegThread"; private Handler handler; private int totalQueued; private int totalCompleted; private FfmpegThreadListener listener; public FfmpegThread(FfmpegThreadListener listener) { this.listener = listener; } @Override public void run() { try { // preparing a looper on current thread // the current thread is being detected implicitly Looper.prepare(); Log.i(DEBUG_TAG, "FfmpegThread entering the loop"); // now, the handler will automatically bind to the // Looper that is attached to the current thread // You don't need to specify the Looper explicitly handler = new Handler(); // After the following line the thread will start // running the message loop and will not normally // exit the loop unless a problem happens or you // quit() the looper (see below) Looper.loop(); Log.i(DEBUG_TAG, "FfmpegThread exiting gracefully"); } catch (Throwable t) { Log.e(DEBUG_TAG, "FfmpegThread halted due to an error", t); } } // This method is allowed to be called from any thread public synchronized void requestStop() { // using the handler, post a Runnable that will quit() // the Looper attached to our FfmpegThread // obviously, all previously queued tasks will be executed // before the loop gets the quit Runnable handler.post(new Runnable() { @Override public void run() { // This is guaranteed to run on the FfmpegThread // so we can use myLooper() to get its looper Log.i(DEBUG_TAG, "FfmpegThread loop quitting by request"); Looper.myLooper().quit(); } }); } public synchronized void enqueueAudioJob(final Runnable task) { // Wrap FfmpegTask into another Runnable to track the statistics handler.post(new Runnable() { @Override public void run() { try { task.run(); } finally { // register task completion synchronized (FfmpegThread.this) { totalCompleted++; } // tell the listener something has happened signalUpdate(); } } }); totalQueued++; // tell the listeners the queue is now longer signalUpdate(); } public synchronized int getTotalQueued() { return totalQueued; } public synchronized int getTotalCompleted() { return totalCompleted; } // Please note! This method will normally be called from the ffmpeg thread. // Thus, it is up for the listener to deal with that (in case it is a UI component, // it has to execute the signal handling code in the UI thread using Handler - see // FfmpegQueueActivity for example). private void signalUpdate() { if (listener != null) { listener.handleFfmpegThreadUpdate(); } } }